package com.wjy.myupdateapp.updater.net;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.widget.Toast;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created by wjy.
 * Date: 2019/11/19
 * Time: 11:33
 * Describe: ${describe}
 */
public class OkhttpNetManager implements INetManager {

    private static OkHttpClient sOkhttpClient;

    private static Handler sHandler = new Handler(Looper.getMainLooper());

    static {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(5*1000, TimeUnit.SECONDS);
        builder.readTimeout(20,TimeUnit.SECONDS);//读超时时间
        builder.writeTimeout(20,TimeUnit.SECONDS);//写超时时间
        builder.retryOnConnectionFailure(true);//失败重连
        sOkhttpClient = builder.build();

        //http
        //https  自签名,Okhttp握手错误
//        builder.sslSocketFactory();
    }

    @Override
    public void get(String url, final INetCallBack callBack,Object tag) {
        //requestbuilder -> Request -> Call -> execute/enqueue
        Request.Builder builder = new Request.Builder();
        Request request = builder.url(url).get().tag(tag).build();
        Call call = sOkhttpClient.newCall(request);
//        Response response = call.execute();//同步
        call.enqueue(new Callback() {//异步
            @Override
            public void onFailure(Call call, final IOException e) {
                //非 ui 线程
                sHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callBack.failed(e);//把异常传过去
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {//可能会产生异常
                    final String string = response.body().string();
                    sHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callBack.success(string);
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                    callBack.failed(e);//把异常传过去
                }
            }
        });
    }

    @Override
    public void post(String url,RequestBody requestBody, final INetCallBack callBack) {
        Request.Builder builder = new Request.Builder();
        Request request = builder
                        .url(url)
                        .post(requestBody)//传递请求体   //与get的区别在这里
                        .build();
        Call call = sOkhttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                //非 ui 线程
                sHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callBack.failed(e);//把异常传过去
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {//可能会产生异常
                    final String string = response.body().string();
                    sHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callBack.success(string);
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                    callBack.failed(e);//把异常传过去
                }
            }
        });
    }

    @Override
    public void POST(final Context context, String url, String requestBody, final INetCallBack callBack) {
        MediaType mediaType = MediaType.parse("text/plain; charset=utf-8");
        Request.Builder builder = new Request.Builder();
        Request request = builder
                .url(url)
                .post(RequestBody.create(mediaType,requestBody))//传递请求体   //与get的区别在这里
                .build();
        Call call = sOkhttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                //非 ui 线程
                sHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callBack.failed(e);//把异常传过去
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {//可能会产生异常
                    final String string = response.body().string();
                    sHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                JSONObject jsonObject = new JSONObject(string);
                                String errorMsg = jsonObject.optString("ErrorMsg");
                                boolean isError = jsonObject.optBoolean("IsError");
                                String response = jsonObject.optString("Res");
                                if (!TextUtils.isEmpty(errorMsg) || errorMsg != null){
                                    Toast.makeText(context,errorMsg,Toast.LENGTH_SHORT).show();
                                }
                                callBack.success(response);
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                    callBack.failed(e);//把异常传过去
                }
            }
        });
    }

    @Override
    public void upload(String url, RequestBody requestBody, final INetCallBack callBack) {
        Request.Builder builder = new Request.Builder();
        Request request = builder
                .url(url)
                .post(requestBody)//传递请求体   //与get的区别在这里
                .build();
        Call call = sOkhttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                //非 ui 线程
                sHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callBack.failed(e);//把异常传过去
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {//可能会产生异常
                    final String string = response.body().string();
                    sHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callBack.success(string);
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                    callBack.failed(e);//把异常传过去
                }
            }
        });
    }

    @Override
    public void download(String url, final File targetFile, final INetDownloadCallBack callback,Object tag) {
        if (targetFile.exists()){//判断是否存在
            targetFile.getParentFile().mkdirs();
        }

        Request.Builder builder = new Request.Builder();
        Request request = builder.url(url).get().tag(tag).build();
        Call call = sOkhttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                callback.failed(e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                InputStream is = null;
                OutputStream os = null;
                try {
                    final long totalLen = response.body().contentLength();

                    is = response.body().byteStream();
                    os = new FileOutputStream(targetFile);

                    byte[] buffer = new byte[8*1024];
                    long curLen = 0;

                    int bufferLen = 0;
                    while (!call.isCanceled() && (bufferLen = is.read(buffer)) !=-1){
                        os.write(buffer,0,bufferLen);
                        curLen += bufferLen;

                        final long finalCurLen = curLen;
                        sHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                callback.progress((int) (finalCurLen * 1.0f / totalLen * 100));
                                //*1.0f  原因：一个小的数字除以一个大的数字，正常除的话始终为0，* 1.0f就会转化为float对象
                                //这样除完就是个零点几的小数，再乘以100就是一个几十的数字

                            }
                        });
                    }

                    if (call.isCanceled()){
                        return;
                    }

                    try {
                        targetFile.setExecutable(true,false);//可执行
                        targetFile.setReadable(true,false);//可读
                        targetFile.setWritable(true,false);//可写
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    sHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.success(targetFile);
                        }
                    });
                } catch (final Throwable e) {
                    if (call.isCanceled()){
                        return;
                    }
                    e.printStackTrace();
                    sHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.failed(e);
                        }
                    });
                }finally {
                    if (is != null){
                        is.close();
                    }
                    if (os != null){
                        os.close();
                    }
                }
            }
        });
    }

    @Override
    public void cancel(Object tag) {
        //排队的
        List<Call> queuedCalls = sOkhttpClient.dispatcher().queuedCalls();
        if (queuedCalls != null){
            for (Call call : queuedCalls){
                if (tag.equals(call.request().tag())){
                    call.cancel();
                }
            }
        }

        //正在执行的（正在下载的）
        List<Call> runningCalls = sOkhttpClient.dispatcher().runningCalls();
        if (runningCalls != null){
            for (Call call : runningCalls){
                if (tag.equals(call.request().tag())){
                    call.cancel();
                }
            }
        }
    }
}
